<template>
  <div class="app-container">
    <div class="topDiv">
      <el-row>
        <el-col :span="4">
          <div class="servicePackageListDiv">
            <div class="servicePackageListDivSpan">服务列表</div>
          </div>
          <div>
            <PackageListSide
              @addNode="addNode"
              style="margin: 0 15px 0 5px; background-color: #fff; height: 81vh"
              ref="packageListSide"
              :graph="graph"
            ></PackageListSide>
          </div>
        </el-col>
        <el-col :span="20">
          <div>
            <div class="servicePackageListDiv">
              <el-tooltip
                class="item"
                effect="dark"
                content="保存"
                placement="bottom"
              >
                <el-button
                  type="primary" size="small" @click="saveFn()"
                  class="el-button-primary-style">
                  保 存
                </el-button>
              </el-tooltip>
            </div>
            <MenuBar
              v-if="showContextMenu"
              ref="menuBar"
              @callBack="contextMenuFn"
            />
            <div id="container" class="graphDiv" @click.stop="hideFn"></div>
          </div>
        </el-col>
      </el-row>
    </div>
  </div>
</template>

<script>
  import {Graph, Shape, Node, Addon, Cell, Path} from "@antv/x6";
  import PackageListSide from "@/views/appstore/components/ServiceGroupComponents/PackageListSide.vue";
  import database from "@/views/appstore/components/ServiceGroupComponents/nodeTheme/database.vue";
  import onlyin from "@/views/appstore/components/ServiceGroupComponents/nodeTheme/onlyIn.vue";
  import "@antv/x6-vue-shape";
  import MenuBar from "@/views/appstore/components/ServiceGroupComponents/MenuBar.vue";

  export default {
    name: "CreateServiceGroup",
    components: {
      PackageListSide,
      MenuBar,
    },
    data() {
      return {
        graph: "",

        showContextMenu: false,
        gvStoreGroupVo: {
          appIdList: [],
          groupDescription: "",
          groupName: "",
          relationGraph: "",
        },
      };
    },
    methods: {
      addNode(option) {
        const p = this.graph.pageToLocal(option.x, option.y);
        this.graph.addNode(Object.assign({}, option, p));
      },
      initGraph() {
        // 注册节点
        Graph.registerNode(
          "dag-onlyIn",
          {
            inherit: "vue-shape",
            width: 180,
            height: 36,
            component: {
              template: `
                <onlyin/>`,
              components: {
                onlyin,
              },
            },
            ports: {
              groups: {
                top: {
                  position: "top",
                  attrs: {
                    circle: {
                      r: 4,
                      magnet: true,
                      stroke: "#C2C8D5",
                      strokeWidth: 1,
                      fill: "#fff",
                    },
                  },
                },
                bottom: {
                  position: "bottom",
                  attrs: {
                    circle: {
                      r: 4,
                      magnet: true,
                      stroke: "#C2C8D5",
                      strokeWidth: 1,
                      fill: "#fff",
                    },
                  },
                },
              },
            },
          },
          true
        );
        Graph.registerNode(
          "dag-node",
          {
            inherit: "vue-shape",
            width: 180,
            height: 36,
            component: {
              template: `
                <database/>`,
              components: {
                database,
              },
            },
            ports: {
              groups: {
                top: {
                  position: "top",
                  attrs: {
                    circle: {
                      r: 4,
                      magnet: true,
                      stroke: "#C2C8D5",
                      strokeWidth: 1,
                      fill: "#fff",
                    },
                  },
                },
                bottom: {
                  position: "bottom",
                  attrs: {
                    circle: {
                      r: 4,
                      magnet: true,
                      stroke: "#C2C8D5",
                      strokeWidth: 1,
                      fill: "#fff",
                    },
                  },
                },
              },
            },
          },
          true
        );

        Graph.registerEdge(
          "dag-edge",
          {
            inherit: "edge",
            attrs: {
              line: {
                stroke: "#C2C8D5",
                strokeWidth: 2,
                targetMarker: {
                  name: "block",
                  width: 12,
                  height: 8,
                },
              },
            },
          },
          true
        );
        Graph.registerConnector(
          "algo-connector",
          (s, e) => {
            const offset = 4;
            const deltaY = Math.abs(e.y - s.y);
            const control = Math.floor((deltaY / 3) * 2);

            const v1 = {x: s.x, y: s.y + offset + control};
            const v2 = {x: e.x, y: e.y - offset - control};

            return Path.normalize(
              `M ${s.x} ${s.y}
           L ${s.x} ${s.y + offset}
           C ${v1.x} ${v1.y} ${v2.x} ${v2.y} ${e.x} ${e.y - offset}
           L ${e.x} ${e.y}
          `
            );
          },
          true
        );

        const graph = new Graph({
          grid: {
            size: 10,
            visible: true,
            type: "dot", // 'dot' | 'fixedDot' | 'mesh'
            args: {
              color: "#a05410", // 网格线/点颜色
              thickness: 1, // 网格线宽度/网格点大小
            },
          },
          background: {
            color: "#ededed", // 设置画布背景颜色
          },
          container: document.getElementById("container"),
          panning: {
            // enabled: true,
            eventTypes: ["leftMouseDown", "mouseWheel"],
          },
          highlighting: {
            magnetAdsorbed: {
              name: "stroke",
              args: {
                attrs: {
                  fill: "#fff",
                  stroke: "#31d0c6",
                  strokeWidth: 4,
                },
              },
            },
          },
          connecting: {
            snap: true,
            allowBlank: false,
            allowLoop: false,
            highlight: true,
            connector: "algo-connector",
            connectionPoint: "anchor",
            anchor: "center",
            validateMagnet() {
              // return magnet.getAttribute('port-group') !== 'top'

              // 限制连线配置
              return true;
            },
            createEdge() {
              return graph.createEdge({
                shape: "dag-edge",
                attrs: {
                  line: {
                    strokeDasharray: "5 5",
                    targetMarker: {
                      name: "block",
                      width: 12,
                      height: 8,
                    },
                  },
                },
                zIndex: -1,
              });
            },
          },
          selecting: {
            enabled: true,
            multiple: true,
            rubberEdge: true,
            rubberNode: true,
            modifiers: "shift",
            rubberband: true,
          },
          keyboard: true,
          clipboard: true,
          history: true,
          // height: 700,
        });
        this.graph = graph;

        graph.on("edge:contextmenu", ({e, x, y, edge, view}) => {
          console.log("----", x, y, view);
          this.showContextMenu = true;
          this.$nextTick(() => {
            // this.$refs.menuBar.initFn(e.offsetX, e.offsetY, {
            this.$refs.menuBar.initFn(
              x + 290,
              y + 20,
              {
                type: "edge",
                item: edge,
              },
              "create"
            );
          });
        });

        graph.on("node:contextmenu", ({e, x, y, node, view}) => {
          console.log("++++", e, x, y, view);
          this.showContextMenu = true;

          this.$nextTick(() => {
            // this.$refs.menuBar.setItem({ type: 'node', item: node })
            const p = graph.localToPage(x, y);
            this.$refs.menuBar.initFn(
              p.x - 220,
              p.y - 70,
              {type: "node", item: node},
              "create"
            );
          });
        });

        graph.on("edge:connected", ({edge}) => {
          const source = graph.getCellById(edge.source.cell);
          const target = graph.getCellById(edge.target.cell);

          // 只允许输入
          if (target.data.type === "output") {
            return graph.removeEdge(edge.id);
          }

          // 只允许输出
          if (source.data.type === "onlyIn") {
            return graph.removeEdge(edge.id);
          }

          // 如果线源头的一端链接桩只允许输入
          if (/in/.test(edge.source.port)) {
            return graph.removeEdge(edge.id);
          }

          // 目标一端链接桩只允许输出
          if (/out/.test(edge.target.port)) {
            return graph.removeEdge(edge.id);
          }

          if (source.data.type === "condition") {
            console.log(source);
            console.log(target);
            console.log(edge);
            if (target.data.t === edge.id || target.data.f === edge.id) {
              return graph.removeEdge(edge.id);
            }
            this.$refs.dialogCondition.visible = true;
            this.$refs.dialogCondition.init(source.data, edge);
          }

          edge.attr({
            line: {
              strokeDasharray: "",
            },
          });
        });

        graph.on("node:change:data", ({node}) => {
          const edges = graph.getIncomingEdges(node);
          const {status} = node.getData();
          edges?.forEach((edge) => {
            if (status === "running") {
              edge.attr("line/strokeDasharray", 5);
              edge.attr(
                "line/style/animation",
                "running-line 30s infinite linear"
              );
            } else {
              edge.attr("line/strokeDasharray", "");
              edge.attr("line/style/animation", "");
            }
          });
        });
      },
      contextMenuFn(type, node) {
        switch (type) {
          case "remove":
            if (node.type === "edge") {
              this.graph.removeEdge(node.item.id);
            } else if (node.type === "node") {
              this.graph.removeNode(node.item.id);
              this.$refs.packageListSide.filterPackageList();
            }
            break;
          case "source":
            this.$refs.dialogMysql.visible = true;
            this.$refs.dialogMysql.init(node);
            break;
        }
        this.showContextMenu = false;
      },
      hideFn() {
        this.showContextMenu = false;
      },
      saveFn() {
        // localStorage.setItem(
        //   "x6Json",
        //   JSON.stringify(this.graph.toJSON({diff: true}))
        // );
        let graphInfo = this.graph.toJSON({diff: true});
        if (graphInfo.cells.length === 0) {
          this.$message.warning("请先选择数据");
          return;
        }
        this.gvStoreGroupVo.appIdList = [];
        graphInfo.cells.forEach((ele) => {
          if (ele.shape === "dag-node") {
            this.gvStoreGroupVo.appIdList.push(ele.data.appId);
          }
        });
        this.gvStoreGroupVo.relationGraph = JSON.stringify(graphInfo);
        this.$appStoreApi.saveGroupInfo(this.gvStoreGroupVo).then((res) => {
          if (res && res.code === 200) {
            this.$message.success("保存服务组成功！");
            this.$router.push({
              name: "ServiceGroup",
            });
          }
        });
      },
    },
    beforeMount() {
      if (this.$route.params.serviceGroupName === undefined) {
        this.$router.push({
          name: "ServiceGroup",
        });
      } else {
        this.gvStoreGroupVo.groupDescription =
          this.$route.params.serviceGroupDesc;
        this.gvStoreGroupVo.groupName = this.$route.params.serviceGroupName;
      }
    },
    mounted() {
      this.initGraph();
    },
  };
</script>

<style lang="css" scoped>
  .app-container {
    padding: 0;
    margin: 0;
    width: 100%;
  }

  .topDiv {
    background-color: #eff4f9;
    margin: 10px;
    height: 92vh;
  }

  .graphDiv {
    border: 1px solid #ededed;
    height: 81vh;
    /* width: ; */
    margin: 0 10px 0 5px;
  }

  .servicePackageListDiv {
    border: 1px solid #304156;
    height: 40px;
    margin: 20px 0;
    /* width: 100%; */
    background-color: #304156;
    display: flex;
    /*justify-content: space-around;*/
    justify-content: right;
    align-items: center;
  }

  .servicePackageListDivSpan {
    color: white;
    width: 95%;
  }

  .item {
    text-align: center;
    margin-right: 20px;
  }

  /*::v-deep .el-button--primary {*/
  /*  background-color: #304156;*/
  /*  border-color: #ededed;*/
  /*}*/
</style>
